/*记录常用的函数*/

/* --------------操作cookies---------------*/

export function setCookies(key,value,days){ //days为有效天数
   let day = new Date(Date.now() + days * 24 * 60 * 60 * 1000);
   let valueTemp = encodeURIComponent(value); //编码（cookie值不支持 ; , 空白符 等，所以需要编码）
   document.cookie = `${key}=${valueTemp};expires=${day.toUTCString()}` //expires值为UTC格式的
 }

export function getCookieByName(key){
  let target = document.cookie.split(';').find(function(value,index){
    return value.split('=')[0].trim() === key  //发现有时获取的key前面有空格，所以使用trim处理一下
  })
  return target ? decodeURIComponent(target.split("=")[1]) : null;
}

export function removeCookie(key){
    setCookies(key,'0',-1)
}

/* -----------------------------------------*/

/* --------------节流函数--------------------*/

/**
 * 节流函数
 * @method throttle
 * @param  {Function} fn      待执行的函数
 * @param  {Number}   delay   延时
 * @param  {Number}   atleast 最小执行间隔
 * @return {[type]}           返回节流函数
 */
export function throttle (fn, delay, atleast) {
  let timer = null
  let startTime = new Date()

  return function () {
    let context = this
    let args = arguments
    let curTime = new Date()

    clearTimeout(timer)
    if (curTime - startTime >= atleast) {
      fn.apply(context, args)   // apply 指定函数指向的 上下文(this) 和 参数列表
      startTime = curTime
    } else {
      timer = setTimeout(function () {
        fn.apply(context, args)
        startTime = curTime
      }, delay)
    }
  }
}

/* -----------------------------------------*/


/* --------------数据处理--------------------*/

/**
 * 处理字符串中的空格
 * @method trimString
 * @param  {String}   str  传入待处理的字符串
 * @param  {Number}   type 处理类型  1--处理掉所有的空格 2--处理前空格 3--处理后空格 4--处理前后空格
 * @return {String}        返回处理后的字符串
 */
export function trimString(str,type = 1){
  switch (type) {
    case 1:
      return str.replace(/\s+/g,'')
      break;
    case 2:
      return str.replace(/^\s+/,'')
      break;
    case 3:
      return str.replace(/\s+$/,'')
      break;
    case 4:
      return str.replace(/(^\s+)|(\s+$)/g,'')
      break;
    default:
      return str
  }
}

/**
 * 统计指定字符在字符串中出现的次数
 * @param {string} str 目标字符串
 * @param {string} char 需要统计的字符
 */
export function countChar (str = '', char = '') {

  return str.split(char).length ? str.split(char).length - 1 : false;
}


/**
 * 判断对象的具体类型
 * @method getType
 * @param  {Object} target 传入带判断的对象
 * @return {String}        返回类型名
 */
export function getType(target){
  let types = {}
  let temp = Object.prototype.toString.call(target)
  //types映射类型
  'Boolean Number String Null Undefined Symbol Function Array Date RegExp Object Error NodeList'.split(' ').map(function(value,index){
    types[`[object ${value}]`] = value.toLowerCase()
  })

  if (types[temp]) {
    return types[temp]
  }else if (temp.indexOf('HTML') !== -1) {
    return 'element'
  }else {
    return
  }
}


/**
 * 实现深拷贝
 * @method deepCopy
 * @param  {Object} target 目标对象
 * @return {Object}        返回复制的对象
 */
export function deepCopy( target ){
  if(typeof target !== 'object') return ;
  //判断目标类型，来创建返回值
  var newObj = target instanceof Array ? [] : {};

  for(let item in target){
    //只复制元素自身的属性，不复制原型链上的
    if(target.hasOwnProperty(item)){
      newObj[item] = typeof target[item] == 'object' ? deepCopy(target[item]) : target[item]
    }
  }
  return newObj
}


/** 对象中指定的属性的旧值替换为新值
 * @param obj 需要操作的对象
 * @param key 指定的key
 * @param oldValue 旧值
 * @param value 新值
 */
export const setValueOfSpecifiedKey = function ( obj , key , oldValue , value) {
  if (!obj) return;
  if (typeof obj !== 'object') return;
  for (let item in obj) {
      if (obj.hasOwnProperty(item)) {
          if (typeof obj[item] == 'object') {
              setValueOfSpecifiedKey(obj[item] , key ,oldValue , value);
          } else {
              if (item == key && obj[item] == oldValue) {
                  obj[item] = value;
              }
          }
      }
  }
}

/**
 * 将对象转换为Formdata
 * @param {object} obj 待转换对象
 */
export function objToFormdata(obj = {}) {
  let keys = Object.keys(obj),
      temp = new FormData();

  keys.forEach(key => {
      temp.append(key,obj[key])
  })

  return temp;
}

/**
 * 数组去重
 * @param {array} arr 目标数组
 */
export function uniqueArray(arr = []) {
  return [... new Set(arr)]
}

/**
 * 将数组延长到指定长度
 * @param {Array} array 目标数组
 * @param {Number} _length 指定长度
 * @param {any} _value 填充物
 */
export function extendArray(array,_length,_value){
  while(array.length < _length){
    array.push(_value);
  }
}

/**
 * 返回指定长度的数组；可用于遍历场景
 * @param {number} length 必选 指定数组的长度
 * @param {any}} item 可选 指定数据的填充项
 */
export function createArrayByLength(length,item = '') {
  return new Array(length).fill(item);
}

/**
 * 选取目标数组中最大或者最小的数字  可转换为数字的元素都会参与判断,不能转换为数组的则会忽略
 * @param {Array} array 目标数组，数组成员可以为非数字
 * @param {boolean} type 返回最大或者最小 true = Max   false = Min
 */
export function findMaxOrMinNumberInArray (array , type = true) {
  let temp = null;
  if (array.length < 1) {
    return ;
  }
  // 本来想用sort排序，再取第一个的，但是sort会改变原数组
  array.forEach( (value,index) => {
    let _value = Number(value);
    if (getType(temp) === 'null') { // 取第一个非NaN的值作为temp的初始值
      if (!isNaN(_value)) {
        temp = _value;
      }
    } else {
      if (!isNaN(_value)) {
        if (type) {
          temp = (temp < _value) ? _value : temp;
        } else {
          temp = (temp > _value) ? _value : temp;
        }
      }
    }
  });
  return temp;
}
/**
 * 交换数组的两个指定元素
 * @param {Array} array 目标数组
 * @param {Number} index1 交换目标的索引
 * @param {Number} index2 交换目标的索引
 */
export function switchItem(array , index1 , index2) {
  let _length = array.length;
  if (_length < index1 || _length < index2) {
    return;
  }
  /*
  // 利用第三方变量的方式进行交换
  let temp = array[index1];
  array[index1] = array[index2];
  array[index2] = temp;
  */
  /*
  // 利用数组工具函数的方式
  array.splice(index2,1,...array.splice(index1, 1 , array[index2]));
  */
  // 利用ES6的解构赋值
  [array[index1],array[index2]] = [array[index2],array[index1]];
}

/**
 * 返回指定范围内的随机整数（包括边界）
 * @method randomNumber
 * @param  {Number}     from 起始值 默认值为0
 * @param  {Number}     to   结束值 默认值为10
 * @return {Number}          返回一个随机整数
 */
export function randomNumber(from = 0,to = 10){ //此处不要用round 会导致随机值分布不均
  let min = Math.ceil(from)
  let max = Math.floor(to)

  return Math.floor(Math.random() * (max - min + 1)) + min
}



/* -----------------------------------------*/


/* --------------日期相关--------------------*/

/**
 * 计算距离指定日期的时间差
 * @method deadTime
 * @param  {String} time 特定格式的时间字符串('2017/12/05 15:00:00') ps:注意都必须是两位    '2017-12-05T15:00:00'这种格式会有8个小时的时区差
 * @return {Object}      返回一个包含天数，小时，分钟，秒的对象
 */
export function deadTime(time){
  if (!time) {
    return
  }

  let start = new Date(),
      end = new Date(time),
      s = end.getTime() - start.getTime();

  if (s < 0) {
    return
  }

  let day = Math.floor(s/1000/3600/24),
      hour = Math.floor(s/1000/3600) % 24,
      minute = Math.floor(s/1000/60) % 60,
      second = Math.floor(s / 1000) % 60;

  return {
    day,
    hour,
    minute,
    second
  }
}
/**
 * 返回一个指定范围的日期数组
 * @param {String} start 起始日期，要符合格式 '2018-02-01'
 * @param {String} end 结束日期 
 * @param {String} spliter 指定的分隔符,默认为空格 '-'
 * @return {Array} 返回一个日期列表 
 */
export function getTimeList(start = '2018-01-01',end = '2018-01-02',spliter = '-'){
  let res = [];
  let st = start.split('-');
  let et = end.split('-');
  let startTime = new Date(st[0],st[1]-1,st[2]).getTime();
  let endTime = new Date(et[0],et[1]-1,et[2]).getTime();

  for(let i = startTime ; i <= endTime ; ){
    res.push(this.formatTime(i,''));
    i += 24 * 60 * 60 * 1000;
  }

  return res;
}
/**
 * 将毫秒时间戳转为年月日格式时间
 * @param {Number} time 标准时间到目的时间的毫秒数
 * @param {String} spliter 指定分隔符
 */
export function formatTime(time,spliter = '-'){
  let date = new Date(time);
  let year = date.getFullYear();
  let month = (date.getMonth() + 1) > 10 ? date.getMonth() + 1 : '0' +  (date.getMonth() + 1);
  let day = date.getDate() > 10 ? date.getDate() : '0' + date.getDate();
  return `${year}${spliter}${month}${spliter}${day}`
}


/* -----------------------------------------*/



/* --------------样式相关--------------------*/
/**
 * 判断element中是否有targetClass
 * @method hasClass
 * @return {Boolean}      返回判断后的boolean值
 */
export function hasClass(element,targetClass){
  if (!targetClass) {
    return false
  }
  if (element.classList) { //IE9及低版本不支持classList
    return element.classList.contains(targetClass)
  }else {
    let classname = element.className
    if (classname && this.trimString(classname,1) !== '') {
      let temp = classname.split(/\s+/g)
      return temp.indexOf(targetClass) !== -1
    }
  }
}
/**
 * 为nodelist或者element增加样式
 * @method addClass
 * @param  {Object} obj         element或者nodelist
 * @param  {String} targetClass class
 */
export function addClass(obj,targetClass){
  if (!targetClass && ['element','nodelist'].indexof(this.getType(obj)) === -1) {
    return false
  }

  if (obj.length) {
    [...obj].forEach((value,index) => {
      this.addElementClass(value,targetClass)
    })
  }else {
    this.addElementClass(obj,targetClass)
  }
}

/**
 * 专为element增加样式
 * @method addClass
 * @param  {Object} obj         element
 * @param  {String} targetClass class
 */
export function addElementClass (element,targetClass){
  if (element.classList) {
    element.classList.add(targetClass)
  }else {
    if (element.className && !this.hasClass(element,targetClass)) {
      element.className += ' ' + targetClass
    }
  }
}

/**
 * 移除元素指定的样式
 * @method removeClass
 * @param  {element}    obj         目标元素，element或者nodelist
 * @param  {String}    targetClass  指定样式
 */
export function removeClass (obj,targetClass){
  if(obj.length){
    [...obj].forEach((value,index) => {
      this.removeElementClass(value,targetClass)
    })
  }else{
    this.removeElementClass(obj,targetClass)
  }
}

export function removeElementClass (element,targetClass){
  if (element.classList) {
    element.classList.remove(targetClass)
  }else {
    if (element.className && this.hasClass(element, targetClass)) {
      element.className = element.className.replace(new RegExp('\\s+' + targetClass + '\\s+'), '')
    }
  }
}

/**
 * 设置或者获取样式
 * @param  {HTMLelement} element 传入目标元素
 * @param  {String/Object} o     设置样式时传入对象；获取样式时传入样式名
 * @return {String}              获取样式时，返回对应样式的Value字符串（带着高度的）
 */
export function css(element,o){
  if (!element) {
    return false
  }

  if (o && (this.getType(o) === 'object') && JSON.stringify(o) !== '{}') { //传入对象且对象不为空
    for (let attr in o) {
      element.style[attr] = o[attr]
    }
  }else if(o && (this.getType(o) === 'string')){
    return window.getComputedStyle(element,null).getPropertyValue(o)
  }
}

/**
 * 解析transform tranlate的value值
 * @param  {String} which      指定获取哪个方向的tranlate x,y,z
 * @param  {String} transform   transform的值
 * @return {[type]}          返回value值
 */
export function getTranslateValue (which, transform) { // z:matrix3d(1, 0, 0, 0, 0, 1, 0, 0, 0, 0, 1, 0, 0, 0, 1.2, 1)   x y :matrix(1, 0, 0, 1, 1.2, 0)
  let temp = which === 'z' ? transform.slice(9, -1).split(',') : transform.slice(7, -1).split(',')
  let index = 0
  switch (which) {
    case 'x':
      index = 4
      break
    case 'y':
      index = 5
      break
    case 'z':
      index = 14
      break
    default:
  }
  return window.parseFloat(temp[index])
}

/**
 * 返回随机的 HEX颜色
 */
export function getRandomColor(){ //Number对象重写了toString,可以指定机制；再将十六进制数字符串处理为 HEXcolor
  return `#${Math.random().toString(16).substring(2).substr(0,6)}`;
}

/**
 * 将HEX格式的颜色转换为RGB格式
 * @param {String} hexString 待转换的HEX格式的颜色,需以‘#’开头
 * @param {Number} a 可选，指定透明度
 * @returns {String} 返回转换后的rgb(a)格式的颜色字符串
 */
export function colorToRGB(hexString , a = undefined) {

  let hex = /^#([0-9a-fA-f]{3}|[0-9a-fA-f]{6})$/
  let temp = [];
  if (!hex.test(hexString)) { // 格式不符合，返回false
    return false;
  }

  if (hexString.length === 4) { // 处理#000格式为#000000
    hexString = `#${hexString.substr(1).split('').map( (item) => `${item}${item}`).join('')}`;
  }
  
  hexString = hexString.substr(1);

  for (let x = 0 ; x < hexString.length - 1; x += 2) { // 获取r,g,b对应的不同的hex数字,并转换为10进制
    temp.push(Number.parseInt(hexString.substr(x,2),16));
  }

  if( a !== undefined && a >= 0 && a <=1) {
    return `RGBA(${temp.join(',')},${a})`
  }

  return `RGB(${temp.join(',')})`
}

/**
 * rem适配body字体
 * @param  {Number} _client 传入适配的参考标准，默认参考为320
 */
export function remFontSize(_client = 320){
    var docEl = document.documentElement,
        resizeEvt = 'orientationchange' in window ? 'orientationchange' : 'resize',
        recalc = function() {
            var clientWidth = docEl.clientWidth;
            if (!clientWidth) return;
            docEl.style.fontSize = 10 * (clientWidth / _client) + 'px';
        };
    if (!document.addEventListener) return;
    window.addEventListener(resizeEvt, recalc, false);
    document.addEventListener('DOMContentLoaded', recalc, false);
}

/* -----------------------------------------*/


/* ---------------------工具函数-------------*/

/**
 * 手机类型判断
 * @method isBrowserInfo
 * @param  {String}      type  android iphone ipad micromessenger
 * @return {Boolean}          返回是否是传入类型的boolean值
 */
export function isBrowserInfo(type) {
    switch (type) {
        case 'android':
            return navigator.userAgent.toLowerCase().indexOf('android') !== -1
        case 'iphone':
            return navigator.userAgent.toLowerCase().indexOf('iphone') !== -1
        case 'ipad':
            return navigator.userAgent.toLowerCase().indexOf('ipad') !== -1
        case 'weixin':
            return navigator.userAgent.toLowerCase().indexOf('micromessenger') !== -1
        default:
            return navigator.userAgent.toLowerCase()
    }
}

/**
 * 图片懒加载 图片链接需存放在'data-src'中
 * @param  {NodeList} imgs   图片节点
 * @param  {Num} offset 偏移值
 */
export function lazyLoad(imgs,offset){
	offset = offset || 100;
		if (!imgs || imgs.length < 1) {
			console.log('imgs为空');
			return ;
		}
		[].slice.call(imgs).forEach(function(element,index){
			var rect = element.getBoundingClientRect()
			if (rect.top <= window.innerHeight + offset && rect.right > 0) {
			element.setAttribute('src',element.getAttribute('data-src'))
			}
	})
}

/** 
 * 解析URL中的查询参数，返回所有的参数对象 ?test=123&help=456
 * @return {Object} 返回查询参数对象 {test:'123',help:'456'}
 */
export function getUrlParams() {
	let obj = {};

	if (!window) {
		return; 
	}

  let str = window.location.search || '';
  
  if (str && str.slice(1)) {
    let queryArray = str.slice(1).split('&');
    queryArray.map((query) => {
      let temp = query.split('=');
      if(temp.length > 1) {
      obj[temp[0]] = temp[1];
      }
    })
  }

	return obj;
}

/**
 * 返回指定url中指定参数的值
 * @param {string} name 参数名称
 */
export function getUrlParamsByName(name) {
	// \b 边界   ?<= 向后匹配 字符串转成正则表达式 要 \\
	let reg = new RegExp(`(?<=\\b${name}=)[^&]*`),
	str = location.search || '',
	target = str.match(reg);
	
	if(target) {
		return target[0]
	}

	return;
}

/**
 * 校验文件是否符合指定的类型和大小规范 {isOk : true,size : true,type : true}
 * @param {file} fileList
 * @param {array} typeArray 类型数组 eg:['png','zip']
 * @param {number} sizeKb 文件大小，以kb为单位，默认值为500
 */
export function checkFileTypeAndSize(fileList,typeArray = [],sizeKb = 500) {

  let temp = {
      isOk : true,
      size : true,
      type : true
  };

  typeArray = typeArray.map(item =>{
      return '.' + ('' + item).trim()
  });
  sizeKb = sizeKb * 1000; // kb -> 字节

  fileList.forEach(file => {
      let {name,size} = file,
          _type = '';

      if (name) {
          _type = '' + name.match(/\..+$/g) || '';

          if (!typeArray.includes(_type)) {
              temp.isOk = false;
              temp.type = false;
          }

          if (size > sizeKb) {
              temp.isOk = false;
              temp.size = false;
          }
      }
  })

  return temp;
}


/**
 * 粘贴内容到粘贴板
 * @param {string} str 内容
 */
export function copyTextToClipBoard (str = '') {

  if (document.execCommand) {

      let tempInput = document.createElement('input');

      tempInput.setAttribute('style','height:0,width:0,visibility: hidden;');
      tempInput.setAttribute('value', str);

      document.body.appendChild(tempInput);

      tempInput.select();

      // 复制
      document.execCommand('copy');
      
      // 销毁无用元素
      document.body.removeChild(tempInput);

      console.log('复制成功')
  } else {
      console.log('该浏览器不支持复制')
  }
}


/**
 * 通过链接下载文件
 * @param {string} url 接地址
 */
export function downLoadByUrl(url) {
  if (!url) {
    return;
  }

  // 创建a标签
  const a = document.createElement("a");
  a.style.display = "none";
  a.href = url;
  // 添加 触发下载
  document.body.appendChild(a);
  a.click();
  // 移除
  document.body.removeChild(a);
}
